package com.hytech.lifegame;

import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Debug;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.Preference.OnPreferenceChangeListener;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.widget.Toast;

import com.hytech.utilities.InfoActivity;
import com.hytech.utilities.R;
import com.hytech.utilities.SplashScreenActivity;

public class GameLifeActivity extends Activity {

	static boolean DEBUG = false;

	// This is for starting the life cycles.
	private static final int START_CYCLE_ID = Menu.FIRST;

	// This is for clearing the grid for the "game".
	private static final int CLEAR_GRID_ID = START_CYCLE_ID + 1;

	// This is for opening the preferences.
	private static final int PREFERENCES_ID = CLEAR_GRID_ID + 1;

	// This is for opening the Info page.
	private static final int INFO_ID = PREFERENCES_ID + 1;

	// This is for opening the How To page.
	private static final int HOW_TO_ID = INFO_ID + 1;
	private static final int STOP_TRACE_ID = HOW_TO_ID + 1;

	private static LifeView mGameView = null;

	// are we currently running?
	private static boolean mCurrentlyCycling = false;

	// let's define a very simple preference Activity.
	public static class ThePreferenceActivity extends PreferenceActivity {

		public static final int MINIMUM_GRID_SIZE = 10;
		/** 
		 * Checks that a preference is a valid numerical value
		 */
		Preference.OnPreferenceChangeListener numberCheckListener = new OnPreferenceChangeListener() {

			@Override
			public boolean onPreferenceChange(Preference preference,
					Object newValue) {
				// Check that the string is an integer.
				return numberCheck(newValue);
			}
		};

		/**
		 * Checks that a preference is a valid numerical value then passes it
		 * into the grid.
		 */
		Preference.OnPreferenceChangeListener gridSizeCheckListener = new OnPreferenceChangeListener() {

			@Override
			public boolean onPreferenceChange(Preference preference,
					Object newValue) {
				// Check that the string is an integer.
				if (numberCheck(newValue) && gridSizeCheck(newValue)) {
					
					int target_Size = Integer.parseInt(newValue.toString().trim());
					mGameView.gridSizeChanged(target_Size);
					
					return true;
				} else {
					return false;
				}
			}
		};

		private boolean numberCheck(Object newValue) {
			if (!newValue.toString().equals("")
					&& newValue.toString().matches("\\d*")) {
				return true;
			} else {
				Toast.makeText(
						ThePreferenceActivity.this,
						newValue
								+ " "
								+ getResources().getString(
										R.string.is_an_invalid_number),
						Toast.LENGTH_SHORT).show();
				return false;
			}
		}

		private boolean gridSizeCheck(Object newValue) {
			// so we know this is an integer.
			int target_Size = Integer.parseInt(newValue.toString().trim());

			// we probably need more checks than this over time, so let's stay
			// with this for the moment.
			if (target_Size <= MINIMUM_GRID_SIZE) {
				Toast.makeText(
						ThePreferenceActivity.this,
						newValue
								+ " "
								+ getResources().getString(
										R.string.grid_size_is_too_small)
								+ Integer.toString(MINIMUM_GRID_SIZE) 
								+ ".",
										Toast.LENGTH_SHORT).show();
				return false;
			}

			return true;

		}

		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);

			addPreferencesFromResource(R.xml.preferences);

			// get a handle on preferences that require validation
			Preference delayPreference = getPreferenceScreen().findPreference(
					LifeView.PREF_DELAY_TIME);

			if (delayPreference != null) {
				// add a listener to this.
				delayPreference
						.setOnPreferenceChangeListener(numberCheckListener);
			}

			// get a handle on another preferences that require validation
			Preference gridSizePreference = getPreferenceScreen()
					.findPreference(LifeView.PREF_GRID_SIZE);
			if (gridSizePreference != null) {
				// add a listener to this.
				gridSizePreference
						.setOnPreferenceChangeListener(gridSizeCheckListener);
			}

		}

	}

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Debug.startMethodTracing("/sdcard/life");
		setContentView(R.layout.gamelayout);

		Resources activityResouces = getResources();

		mGameView = (LifeView) findViewById(R.id.GameGrid);
		Drawable gridDrawable = activityResouces
				.getDrawable(R.drawable.basegrid);
		mGameView.loadBaseGrid(gridDrawable);

		Drawable selectionDrawable = activityResouces
				.getDrawable(R.drawable.selectiongrid);
		mGameView.loadSelectedGrid(selectionDrawable);

		mGameView.resetGrids(2);
		
		Drawable markerDrawable = activityResouces
				.getDrawable(R.drawable.marker);
		mGameView.loadGrid(1, markerDrawable);

		startSplashScreen();

	}

	// This creates the Options Menu, nice and easy.
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.add(0, START_CYCLE_ID, 0, R.string.start_cycle);
		menu.add(0, CLEAR_GRID_ID, 0, R.string.clear_grid);
		menu.add(0, PREFERENCES_ID, 0, R.string.preferences);
		menu.add(0, INFO_ID, 0, R.string.info_menu);
		menu.add(0, HOW_TO_ID, 0, R.string.how_to_menu);
		menu.add(0, STOP_TRACE_ID, 0, "Stop Trace");
		return true;
	}

	// This responds to something being picked on the Options Menu.
	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId()) {
		case START_CYCLE_ID:
			toggleCycling();
			return true;

		case CLEAR_GRID_ID:
			clearGrid();
			return true;

		case PREFERENCES_ID:
			runPreferences();
			return true;

		case INFO_ID:
			openInfo();
			return true;

		case HOW_TO_ID:
			openHowTo();
			return true;

		case STOP_TRACE_ID:
			Debug.stopMethodTracing();
			return true;
		default:
			break;
		}

		return super.onMenuItemSelected(featureId, item);
	}

	/**
	 * Cycling is also known as running, This actually just triggers a cycles,
	 * or calls for the next cycle to not happen.
	 */
	private void toggleCycling() {
		mCurrentlyCycling = !mCurrentlyCycling;

		if (mCurrentlyCycling) {
			setTitle(getResources().getText(R.string.title_running));
			mGameView.startCycling();
		} else {
			setTitle(getResources().getText(R.string.title));

			mGameView.stopCycling();
		}
	}

	/**
	 * Clear the game view's grid. Simple pass through.
	 */
	private void clearGrid() {

		maybeStopCycling();

		mGameView.clearGrid();

	}

	/**
	 * Maybe stop cycling the screen. This is called when you want to the screen
	 * to stop cycling, but you aren't sure if it is cycling.
	 */
	private void maybeStopCycling() {
		// if the game is running, toggle the cycling.
		if (mCurrentlyCycling) {
			toggleCycling();
		}
	}

	private void runPreferences() {

		maybeStopCycling();

		Intent preferenceIntent = new Intent(this, ThePreferenceActivity.class);
		startActivity(preferenceIntent);

	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		MenuItem StartCycleItem = menu.findItem(START_CYCLE_ID);
		if (mCurrentlyCycling) {

			StartCycleItem.setTitle(R.string.stop_cycle);
		} else {
			StartCycleItem.setTitle(R.string.start_cycle);
		}
		return super.onPrepareOptionsMenu(menu);
	}

	@Override
	public boolean onTrackballEvent(MotionEvent event) {
		if (mGameView != null) {
			mGameView.parseTrackball(event);
		}

		return super.onTrackballEvent(event);
	}

	// This is the function to open the info page for the application.
	private void openInfo() {

		maybeStopCycling();

		// Launch info activity
		Intent i = new Intent(this, InfoActivity.class);

		i.putExtra(InfoActivity.INFO_ID, R.raw.info);

		startActivity(i);

	}

	// This is the function to open the info page for the application.
	private void openHowTo() {

		maybeStopCycling();

		// Launch info activity
		Intent i = new Intent(this, InfoActivity.class);

		// add data to the intent.
		i.putExtra(InfoActivity.INFO_ID, R.raw.how_to);

		startActivity(i);

	}

	// This is the function to open the info page for the application.
	private void startSplashScreen() {

		// Launch info activity
		Intent i = new Intent(this, SplashScreenActivity.class);

		// add data to the intent.
		i.putExtra(SplashScreenActivity.SPLASH_SCREEN_ID,
				R.drawable.splashscreen);

		startActivity(i);

	}

}
